#!/usr/bin/python

# InnerSpace
# Copyright (C) 1999-2006 Phil Christensen
#
# $Id: actions.py 157 2007-02-11 18:37:33Z phil $
#
# See LICENSE for details

"""
Actions

Stability: somewhat stable

The primary client actions are handled here. This controller
can tell the difference between web and pb clients, and do
the right thing where appropriate.
"""

from inner.space import parser, code

def parse(user, registry, command):
	print str(user) + ': ' + command
	#parse the sentence
	p = parser.Parser(parser.Lexer(command), user, registry)
	#get the verb
	verb = p.get_verb()
	#if we got this far, we're good to go, so execute the verb
	verb.execute(code.get_environment(verb, p))

def logout_code(user_obj):
	if(hasattr(user_obj, '_connection')):
		del user_obj.__dict__['_connection']
	print user_obj, "logged out"
	from inner.space import auth

	auth.user_activate(user_obj)
	system_object = auth.get_registry().get(0)
	if(system_object.has_callable_verb("logout")):
		system_object.call_verb("logout", user_obj)
	auth.user_deactivate()

def unicodify(item):
	if(isinstance(item, dict)):
		result = {}
		for key in item:
			result[unicode(key)] = unicodify(item[key])
		return result
	elif(isinstance(item, list) or isinstance(item, tuple)):
		result = []
		for element in item:
			result.append(unicodify(element))
		if(isinstance(item, tuple)):
			result = tuple(result)
		return result
	elif(isinstance(item, str)):
		return unicode(item)
	elif(isinstance(item, int) or isinstance(item, long) or isinstance(item, float)):
		return item
	elif(isinstance(item, unicode) or item is None):
		return item
	else:
		raise RuntimeError("Can't serialize item '%r' of type: %r" % (item, type(item)))

def ununicodify(item):
	if(isinstance(item, dict)):
		result = {}
		for key in item:
			result[str(key)] = ununicodify(item[key])
		return result
	elif(isinstance(item, list) or isinstance(item, tuple)):
		result = []
		for element in item:
			result.append(ununicodify(element))
		if(isinstance(item, tuple)):
			result = tuple(result)
		return result
	elif(isinstance(item, unicode)):
		return str(item)
	else:
		return item

class RemoteWrapper:
	def __init__(self, connection):
		self.connection = connection
		self.client_type = self.get_type()
	
	def get_type(self):
		from inner.space import pbclient, webclient
		
		if(isinstance(self.connection, pbclient.UserPerspective)):
			return 'pb'
		elif(isinstance(self.connection, webclient.ClientConnector)):
			return 'web'
			
	def set_observations(self, observations):
		if(observations is None):
			raise ValueError, "Cannot set null observations."
		if(self.get_type() == 'pb'):
			return self.connection.client.callRemote('observe', observations)
		elif(self.get_type() == 'web'):
			return self.connection.callRemote('setObservations', observations)
	
	def write(self, text, callback=None, errback=None):
		if not errback:
			def errback(failure):
				print failure
		if not callback:
			def callback(result):
				pass

		if(self.get_type() == 'pb'):
			return self.connection.client.callRemote('write', unicode(text)).addCallback(callback).addErrback(errback)
		elif(self.get_type() == 'web'):
			return self.connection.callRemote('write', unicode(text)).addCallback(callback).addErrback(errback)
	
	def open_editor(self, editor, info, callback=None, errback=None):
		if not errback:
			def errback(failure):
				print failure
		if not callback:
			def callback(result):
				pass

		if(self.get_type() == 'pb'):
			return self.connection.client.callRemote(editor + 'edit', info).addCallback(callback).addErrback(errback)
		elif(self.get_type() == 'web'):
			return self.connection.callRemote(editor + 'edit', info).addCallback(callback).addErrback(errback)


